#include "anydvdhandler.h"
#include <QDebug>
#include <QUrl>

AnydvdHandler::AnydvdHandler()
{
    _isWorking = false;
    _http= new QHttp();
    connect(_http, SIGNAL(done(bool)), this, SLOT(downloadFinish(bool)));
    _downloading = false;
    _readyForInstall = false;
    _process = NULL;
    _path = "C:/temp/";
}

AnydvdHandler::~AnydvdHandler()
{
    qDebug()<<"~AnydvdHandler";
    this->wait();
    if(timer!=NULL)
    {
        delete timer;
    }
    if(_file!=NULL&&_file->isOpen())
        _file->close();
    if(_file!=NULL)
        delete _file;
    if(_http!=NULL)
        delete _http;
    if(_process!=NULL)
        delete _process;
}

void AnydvdHandler::downloadFinish(bool error)
{
    qDebug()<<"AnydvdHandler::downloadFinish()";
    _downloading = false;
    _file->close();
    if(!error)
    {
        qDebug()<<"update anydvd.txt with: "<<_versionDownloading;
        QFile versionFile("anydvd.txt");
        if(versionFile.open(QIODevice::WriteOnly))
        {
            versionFile.write(_versionDownloading.toAscii());
        }
        versionFile.close();
        _readyForInstall = true;        
    }
    else
    {
        qDebug()<<"downloading error";
    }
    this->startWorking();
}

bool AnydvdHandler::downloadUpdaterFile(QString version,QString url,QString fileName)
{    
    qDebug()<<"downloadUpdaterFile(QString version,QString url,QString fileName)";
    _downloading = true;
    QUrl qurl(url);
    qDebug()<<"url: "<<url;
    qDebug()<<"URL: "<<qurl.encodedPath();

    _versionDownloading = version;
    _file = new QFile(_path+fileName);
    _http->setHost(qurl.host());
    _http->get(qurl.path(),_file);
    return true;
}
void AnydvdHandler::run()
{
    qDebug()<<"AnydvdHandler::run()";
    timer = new QTimer;
    connect(timer, SIGNAL(timeout()), this, SLOT(startWorking()));

    timer->setInterval((60*1000)*60);
    timer->start();
    exec();
}
void AnydvdHandler::processStateChanged(QProcess::ProcessState newState )
{
    qDebug()<<"processStateChanged(QProcess::ProcessState newState )";
    qDebug()<<"New state: "<<newState;
}

void AnydvdHandler::processError ( QProcess::ProcessError error )
{
    qDebug()<<"processError ( QProcess::ProcessError error )";
    qDebug()<<"Error: "<<error;
}

void AnydvdHandler::processFinished ( int exitCode, QProcess::ExitStatus exitStatus )
{
    qDebug()<<"processFinished ( int exitCode, QProcess::ExitStatus exitStatus )";
    qDebug()<<"ExitCode: "<<exitCode;
    qDebug()<<"ExitStatus: "<<exitStatus;
    CurrentStatus * currentStatus = CurrentStatus::getInstance();
    currentStatus->setUpdating(false);

    if(exitStatus==QProcess::NormalExit)
    {
        PelicanoWS pelicanows;
        pelicanows.setInstalledAnydvdVersion(_versionDownloading);
        _readyForInstall = false;
        _downloading = false;
        currentStatus->setWatingForReboot(true);
    }

    this->startWorking();

    //timer->start();
}

void AnydvdHandler::processStarted()
{

    qDebug()<<"processStarted ()";
}

void AnydvdHandler::executeUpdate()
{
    qDebug()<<"AnydvdHandler::executeUpdate()";
    //timer->stop();
    if(_process!=NULL)
        delete _process;

    qDebug()<<"_process = new QProcess();";

    _process = new QProcess();
    qDebug()<<"SIGNAL(started())";
    connect(_process, SIGNAL(started()), this, SLOT(processStarted()));
    qDebug()<<"SIGNAL(error())";
    connect(_process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
    qDebug()<<"SIGNAL(finished())";
    connect(_process, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished(int,QProcess::ExitStatus)));
    QStringList args;
    args << "/S";
    qDebug()<<"start(_file->fileName(),args): "<<_file->fileName()<<args[0];
    _process->start(_file->fileName(),args);
}

void AnydvdHandler::startWorking()
{
    qDebug()<<"AnydvdHandler::startWorking()";
    if(_isWorking) return;
    _isWorking = true;
    CurrentStatus *currentStatus = CurrentStatus::getInstance();
    if(!currentStatus->getRipping()&&!currentStatus->getUpdating())
    {
        Settings *settings = Settings::getInstance();
        QTime now = QTime::currentTime();
        if(now>=settings->getTimeFromReboot() && now <=settings->getTimeToReboot())
        {
            if(currentStatus->getWatingForReboot())
            {
                qDebug()<<"ready to reboot";
                WindowsApi win;
                qDebug()<<"rebooting";
                win.reboot();
            }
            else if(_readyForInstall)
            {
                qDebug()<<"ready to update";
                currentStatus->setUpdating(true);
                executeUpdate();
            }
            else if(!_downloading)
            {
                qDebug()<<"ready to check for update";
                checkForUpdate();
            }
        }
    }
    _isWorking = false;
}

QString AnydvdHandler::getVersionDownloaded()
{
    qDebug()<<"AnydvdHandler::getVersionDownloaded";
    QFile toFile("anydvd.txt");
    QByteArray data;
    if(toFile.open(QIODevice::ReadOnly))
    {
        data = toFile.readLine();
    }

    qDebug()<<"Version Downloaded: "<<data;
    return data;
}

bool AnydvdHandler::checkForUpdate()
{
    qDebug()<<"AnydvdHandler::checkForUpdate()";
    try {
        if(!_downloading)
        {
            PelicanoWS pelicanows;
            AnydvdUpdateResponse anydvdVersion = pelicanows.checkForAnydvdUpdates();
            if(anydvdVersion.action == AnydvdUpdateResponse::ANY_DOWNLOAD && anydvdVersion.version != this->getVersionDownloaded())
            {
                if(anydvdVersion.version != this->getVersionInstalled())
                {
                    this->downloadUpdaterFile(anydvdVersion.version,anydvdVersion.url,anydvdVersion.file_name);
                }
            }
        }
    } catch (...) {
        qDebug()<<"An error occurred checking for updates";
        return false;
    }
    return true;

}

QString AnydvdHandler::getVersionInstalled()
{
    qDebug()<<"AnydvdHandler::getVersionInstalled()";
    QString version;
    WCHAR *fileName = L"C:/Program Files (x86)/SlySoft/AnyDVD/AnyDVD.exe";
    DWORD size;
    DWORD handle = 0;
    size = GetFileVersionInfoSize(fileName, &handle);
    BYTE* versionInfo = new BYTE[size];
    if (!GetFileVersionInfo(fileName, handle, size, versionInfo))
    {
        delete[] versionInfo;
        return "";
    }
    // we have version information
    UINT len = 0;
    VS_FIXEDFILEINFO*   vsfi = NULL;
    VerQueryValue(versionInfo, L"\\", (void**)&vsfi, &len);
    version = QString::number(HIWORD(vsfi->dwFileVersionMS));
    version += ".";
    version += QString::number(LOWORD(vsfi->dwFileVersionMS));
    version += ".";
    version += QString::number(HIWORD(vsfi->dwFileVersionLS));
    version += ".";
    version += QString::number(LOWORD(vsfi->dwFileVersionLS));
    delete[] versionInfo;
    qDebug()<<"Version Installed: "<<version;
    return version;
}
